﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using GraphBase.Interfaces;
using ObjectGraph.Core;

namespace GraphBase
{
    public class VertexCollection : IVertexCollection
    {
        public delegate Vertex CreateVertex();
        private delegate ICollection NextVertexes(IVertex vertex);

        List<Vertex> m_vertexes = new List<Vertex>();
        OnVertexAdded m_added;
        OnVertexRemoved m_removed;

        public VertexCollection(OnVertexAdded added, OnVertexRemoved removed)
        {
            m_added = added;
            m_removed = removed;
        }

        public void Add(IVertex vert)
        {
            Vertex vertex = (Vertex)vert;
            zzAdd(vertex);
            if (m_added != null)
                m_added(vertex);
        }

        public void zzAdd(Vertex vert) { m_vertexes.Add(vert); }
        public bool zzRemove(Vertex vert) { return m_vertexes.Remove(vert); }

        public void Remove(IVertex vertex)
        {
            Vertex realVert = (Vertex)vertex;
            realVert.zzPerformRemove();
            if (zzRemove(realVert) &&
                m_removed != null)
                m_removed(realVert);
        }

        public IEnumerator<Vertex> GetVertexEnumerator() { return m_vertexes.GetEnumerator(); }

        #region IVertexCollection Members

        public IEnumerable GetGraphRoots()
        {
            return new FilteringEnumerable<GraphBase.Vertex>(m_vertexes,
                delegate(GraphBase.Vertex vertex) { return vertex.IncomingEdges.Count == 0; });
        }

        public IEnumerable GetGraphLeaves()
        {
            return new FilteringEnumerable<GraphBase.Vertex>(m_vertexes,
                delegate(GraphBase.Vertex vertex) { return vertex.OutgoingEdges.Count == 0; });
        }

        #endregion

        #region ICollection Members

        public void CopyTo(Array array, int index)
        {
            ((ICollection)m_vertexes).CopyTo(array, index);
        }

        public int Count
        {
            get { return m_vertexes.Count; }
        }

        public bool IsSynchronized
        {
            get { return false; }
        }

        public object SyncRoot
        {
            get { return null; }
        }

        #endregion

        #region IEnumerable Members

        public IEnumerator GetEnumerator()
        {
            return ((ICollection)m_vertexes).GetEnumerator();
        }

        #endregion
    }
}
